#include <gtk/gtk.h>
#include <cairo.h>
#include <jni.h>
#include "gwire_gtk_drawable_cairo.h"
#include "gtkwire_databank.h"
#include "gtkwire_widget_GtkCairoDrawable.h"
#include "gtkwire_widget_cairo_CairoGraphics.h"
#include "gtkwire_widget_cairo_CairoPattern.h"

/* Cairo drawing context */
static cairo_t *cr;
/* Integer saved for hastable use */
static int pointer_id[100];
/* Java objects */
static jobject cairo_drawables[100];
/* Cairo patterns */
static GList *cairo_patterns_list = NULL;

/* Returns id for name */
static GHashTable *id_for_name = NULL;
/* pointer to vmachine */
static JavaVM *jvm = NULL;
/* Graphics obj class */
static jclass graphics_class = NULL;
static jmethodID graphics_constructor_id = NULL;
/* widget obj class */
static jclass widget_class = NULL;
static jmethodID widget_exposure_event_id = NULL;
/* CAiroRectangle */
static jclass cairo_graphics_rect_cls = NULL;
static jmethodID cairo_graphics_rect_mid = NULL;
/* CairoPoint class */
static jclass cairo_point_cls;
static jmethodID  cairo_point_constr_mid;

/* Pattern inner */
static void 				add_pattern (int pid, cairo_pattern_t *pattern);
static void 				destroy_pattern (int pid );
static cairo_pattern_t* 		get_pattern (int pid);
/* utils */
static jobject 				get_cairo_graphics_rect_from_bounds( JNIEnv *env, double x1, double y, double width, double height );

typedef struct
{
	gpointer *id;
	cairo_pattern_t *pat;

} PatternID;

JNIEXPORT void JNICALL 
Java_gtkwire_widget_GtkCairoDrawable_initNative (JNIEnv *env, jclass cls)
{
	/* Initialize the jvm global variable */
	(*env)->GetJavaVM (env, &jvm);

	/* Create widgets table */
	id_for_name = g_hash_table_new (g_str_hash, g_str_equal);

	/* CairoGraphics */
	jclass graph_cls_local = (*env)->FindClass (env, "gtkwire/widget/cairo/CairoGraphics");
	graphics_class = (*env)->NewGlobalRef (env, graph_cls_local );
	graphics_constructor_id = (*env)->GetMethodID (env, graphics_class, "<init>", "(IIII)V");

	/* GtkCairoDrawable */
	jclass widget_class_local = (*env)->FindClass (env, "gtkwire/widget/GtkCairoDrawable");
	widget_class = (*env)->NewGlobalRef (env, widget_class_local );
	widget_exposure_event_id 
		= (*env)->GetMethodID (env, widget_class, "exposureEvent", "(Lgtkwire/widget/cairo/CairoGraphics;)V");

	/* CairoExtents */
	jclass cgr_class_local = (*env)->FindClass (env, "gtkwire/widget/cairo/CairoRectangle");
	cairo_graphics_rect_cls = (*env)->NewGlobalRef (env, cgr_class_local);
	cairo_graphics_rect_mid = (*env)->GetMethodID (env, cairo_graphics_rect_cls, "<init>", "(DDDD)V");

	/* CAiroPoint */
	jclass cp_class_local = (*env)->FindClass (env, "gtkwire/widget/cairo/CairoPoint");
	jclass cairo_point_cls = (*env)->NewGlobalRef (env, cp_class_local);
	cairo_point_constr_mid = (*env)->GetMethodID (env, cairo_point_cls, "<init>", "(DD)V");
}

JNIEXPORT void JNICALL
Java_gtkwire_widget_GtkCairoDrawable_initDrawable (JNIEnv *env, jobject java_obj, jstring widget_name, jint cairo_id)
{
	/* Crete name string */
	const char *name_str = (*env)->GetStringUTFChars (env, widget_name, NULL);
	gpointer name_p = (gpointer) name_str;

	/* Get and widget */
	GtkWidget *gtk_cairo_drawable = get_widget (name_str);

	/* Connect exposure event callback */
	g_signal_connect (G_OBJECT (gtk_cairo_drawable), "expose_event",
                    G_CALLBACK (expose_event_callback), NULL);

	/* Save class obj*/
	cairo_drawables[cairo_id] = (*env)->NewGlobalRef (env, java_obj);

	/* Create pointer for id */
	pointer_id[cairo_id] = cairo_id;
	int *id_p;
	id_p = &pointer_id[cairo_id];

	/* Create hash entry name->id*/
	g_hash_table_insert (id_for_name, name_p, (gpointer) id_p);
}

/* Widget exposed */
gboolean
expose_event_callback (GtkWidget *widget, GdkEventExpose *event, gpointer data)
{
	cr = gdk_cairo_create (widget->window);

	int *cairo_id = g_hash_table_lookup (id_for_name, gtk_widget_get_name(widget));
	jobject drawable_obj = cairo_drawables[*cairo_id];

	/* Get env for client jvm. */
	JNIEnv *env;
	if ((*jvm)->AttachCurrentThread (jvm, (void **)&env, NULL) != 0)
	{
		/* some error handling and return? */
		printf("jvm attach error in expose_event_callback");
	}

	jint x = event->area.x;
	jint y = event->area.y;
	jint width = event->area.width;
	jint height = event->area.height;

	jobject graphics_object = (*env)->NewObject (	env,
							graphics_class,
							graphics_constructor_id,
							x,
							y,
							width,
							height);

	/* Send graphics obj */
	(*env)->CallVoidMethod (env, drawable_obj, widget_exposure_event_id, graphics_object);

	cairo_destroy(cr);

	return TRUE;
}



//-------------------------------------------------------------------------------- DRAW CONTEXT
JNIEXPORT jint JNICALL Java_gtkwire_widget_cairo_CairoGraphics_status
  (JNIEnv *env, jobject obj)
{
	return cairo_status (cr);
}

JNIEXPORT void JNICALL Java_gtkwire_widget_cairo_CairoGraphics_set_1source_1rgba
  (JNIEnv *env, jobject obj, jdouble red, jdouble green, jdouble blue, jdouble alpha)
{
	cairo_set_source_rgba (cr,red,green,blue,alpha);
}

JNIEXPORT void JNICALL Java_gtkwire_widget_cairo_CairoGraphics_set_1source
  (JNIEnv *env, jobject obj, jint pid)
{
	cairo_pattern_t *pat = get_pattern (pid);
	cairo_set_source (cr, pat);
}

JNIEXPORT void JNICALL Java_gtkwire_widget_cairo_CairoGraphics_set_1antialias
  (JNIEnv *env, jobject obj, jint antialias)
{
	 cairo_set_antialias (cr, antialias);
}

JNIEXPORT jint JNICALL Java_gtkwire_widget_cairo_CairoGraphics_get_1antialias
  (JNIEnv *env, jobject obj)
{
	return cairo_get_antialias (cr);
}


JNIEXPORT void JNICALL Java_gtkwire_widget_cairo_CairoGraphics_set_1fill_1rule
  (JNIEnv *env, jobject obj, jint fill_rule)
{
	 cairo_set_fill_rule (cr, fill_rule); 
}

JNIEXPORT jint JNICALL Java_gtkwire_widget_cairo_CairoGraphics_get_1fill_1rule
  (JNIEnv *env, jobject obj)
{
	return cairo_get_fill_rule (cr);
}

JNIEXPORT void JNICALL Java_gtkwire_widget_cairo_CairoGraphics_set_1line_1cap
  (JNIEnv *env, jobject obj, jint line_cap)
{
	cairo_set_line_cap (cr, line_cap);
}

JNIEXPORT jint JNICALL Java_gtkwire_widget_cairo_CairoGraphics_get_1line_1cap
  (JNIEnv *env, jobject obj)
{
	return cairo_get_line_cap(cr);
}

JNIEXPORT void JNICALL Java_gtkwire_widget_cairo_CairoGraphics_set_1line_1join
  (JNIEnv *env, jobject obj, jint line_join)
{
	cairo_set_line_join (cr, line_join);
}

JNIEXPORT jint JNICALL Java_gtkwire_widget_cairo_CairoGraphics_get_1line_1join
  (JNIEnv *env, jobject obj)
{
	return  cairo_get_line_join(cr);
}


JNIEXPORT jdouble JNICALL Java_gtkwire_widget_cairo_CairoGraphics_get_1line_1width
  (JNIEnv *env, jobject obj)
{
	return cairo_get_line_width (cr);
}

JNIEXPORT void JNICALL Java_gtkwire_widget_cairo_CairoGraphics_set_1miter_1limit
  (JNIEnv *env, jobject obj, jdouble miter_limit)
{
	cairo_set_miter_limit (cr, miter_limit);
}

JNIEXPORT jdouble JNICALL Java_gtkwire_widget_cairo_CairoGraphics_get_1miter_1limit
  (JNIEnv *env, jobject obj)
{
	return cairo_get_miter_limit (cr);
}

JNIEXPORT void JNICALL Java_gtkwire_widget_cairo_CairoGraphics_set_1operator
  (JNIEnv *env, jobject obj, jint operator)
{
	cairo_set_operator (cr, operator);
}

JNIEXPORT jint JNICALL Java_gtkwire_widget_cairo_CairoGraphics_get_1operator
  (JNIEnv *env, jobject obj)
{
	return cairo_get_operator (cr);
}

JNIEXPORT void JNICALL Java_gtkwire_widget_cairo_CairoGraphics_set_1tolerance
  (JNIEnv *env, jobject obj, jdouble tolerance)
{
	cairo_set_tolerance (cr, tolerance); 
}

JNIEXPORT jdouble JNICALL Java_gtkwire_widget_cairo_CairoGraphics_get_1tolerance
  (JNIEnv *env, jobject obj)
{
	return cairo_get_tolerance (cr);
}

JNIEXPORT void JNICALL Java_gtkwire_widget_cairo_CairoGraphics_clip_1preserve
  (JNIEnv *env, jobject obj)
{
	cairo_clip_preserve (cr);
}

JNIEXPORT jobject JNICALL Java_gtkwire_widget_cairo_CairoGraphics_clip_1extents
  (JNIEnv *env, jobject obj)
{
	double *x1;
	double *y1;
	double *x2;
	double *y2;

	cairo_clip_extents (cr, x1, y1, x2, y2);

	return get_cairo_graphics_rect_from_bounds (env, *x1, *y1, *x2 - *x1, *y2 - *y1);
}

JNIEXPORT void JNICALL Java_gtkwire_widget_cairo_CairoGraphics_reset_1clip
  (JNIEnv *env, jobject obj)
{
	cairo_reset_clip (cr);
}

JNIEXPORT void JNICALL Java_gtkwire_widget_cairo_CairoGraphics_fill_1preserve
  (JNIEnv *env, jobject obj)
{
	cairo_fill_preserve (cr);
}

JNIEXPORT jobject JNICALL Java_gtkwire_widget_cairo_CairoGraphics_fill_1extents
  (JNIEnv *env, jobject obj)
{
	double *x1;
	double *y1;
	double *x2;
	double *y2;

	cairo_fill_extents (cr, x1, y1, x2, y2);

	return get_cairo_graphics_rect_from_bounds (env, *x1, *y1, *x2 - *x1, *y2 - *y1);
}

JNIEXPORT jboolean JNICALL Java_gtkwire_widget_cairo_CairoGraphics_in_1fill
  (JNIEnv *env, jobject obj, jdouble x, jdouble y)
{
	if( cairo_in_fill (cr, x, y) ) return TRUE;
	
	return FALSE;
}

JNIEXPORT void JNICALL Java_gtkwire_widget_cairo_CairoGraphics_mask
  (JNIEnv *env, jobject obj, jint pid)
{
	cairo_mask (cr, get_pattern (pid));
}

JNIEXPORT void JNICALL Java_gtkwire_widget_cairo_CairoGraphics_paint
  (JNIEnv *env, jobject obj)
{
	   cairo_paint (cr);
}

JNIEXPORT void JNICALL Java_gtkwire_widget_cairo_CairoGraphics_paint_1with_1alpha
  (JNIEnv *env, jobject obj, jdouble alpha)
{
	cairo_paint_with_alpha (cr, alpha);
}

JNIEXPORT void JNICALL Java_gtkwire_widget_cairo_CairoGraphics_stroke_1preserve
  (JNIEnv *env, jobject obj)
{
	cairo_stroke_preserve (cr);
}

JNIEXPORT jobject JNICALL Java_gtkwire_widget_cairo_CairoGraphics_stroke_1extents
  (JNIEnv *env, jobject obj)
{
	double *x1;
	double *y1;
	double *x2;
	double *y2;

	cairo_stroke_extents (cr, x1, y1, x2, y2);

	return get_cairo_graphics_rect_from_bounds (env, *x1, *y1, *x2 - *x1, *y2 - *y1);	
}

JNIEXPORT jboolean JNICALL Java_gtkwire_widget_cairo_CairoGraphics_in_1stroke
  (JNIEnv *env, jobject obj, jdouble x, jdouble y)
{
	if (cairo_in_stroke (cr, x, y)) return TRUE;
	
	return FALSE;
}

JNIEXPORT void JNICALL Java_gtkwire_widget_cairo_CairoGraphics_fill
  (JNIEnv *env, jobject obj)
{
	cairo_fill (cr);
}

JNIEXPORT void JNICALL Java_gtkwire_widget_cairo_CairoGraphics_clip
  (JNIEnv *env, jobject obj)
{
	cairo_clip (cr);
}

JNIEXPORT void JNICALL Java_gtkwire_widget_cairo_CairoGraphics_set_1source_1rgb
  (JNIEnv *env, jobject obj, jdouble red, jdouble green, jdouble blue)
{
	cairo_set_source_rgb (cr, red ,green, blue);	
}

JNIEXPORT void JNICALL Java_gtkwire_widget_cairo_CairoGraphics_set_1line_1width
  (JNIEnv *env, jobject obj, jdouble width)
{
	cairo_set_line_width (cr, width);
}

JNIEXPORT void JNICALL Java_gtkwire_widget_cairo_CairoGraphics_stroke
  (JNIEnv *env, jobject obj)
{
	cairo_stroke(cr);
}

//--------------------------------------------------------------------------------------- PATH
/* cairo_new_path */
JNIEXPORT void JNICALL Java_gtkwire_widget_cairo_CairoGraphics_new_1path
  (JNIEnv *env, jobject obj)
{
	cairo_new_path (cr);
}

/* sub_path */
JNIEXPORT void JNICALL Java_gtkwire_widget_cairo_CairoGraphics_new_1sub_1path
  (JNIEnv *env, jobject obj )
{
	cairo_new_sub_path (cr);
}

/* close_path */
JNIEXPORT void JNICALL Java_gtkwire_widget_cairo_CairoGraphics_close_1path
  (JNIEnv *env, jobject obj)
{
	cairo_close_path (cr);
}

/* cairo_arc */
JNIEXPORT void JNICALL Java_gtkwire_widget_cairo_CairoGraphics_arc
  (JNIEnv *env, jobject obj, jdouble xc, jdouble yc, jdouble radius, jdouble angle1, jdouble angle2)
{
	cairo_arc (cr, xc, yc, radius, angle1, angle2);
}

/* arc_negative */
JNIEXPORT void JNICALL Java_gtkwire_widget_cairo_CairoGraphics_arc_1negative
  (JNIEnv *env, jobject obj, jdouble xc, jdouble yc, jdouble radius, jdouble angle1, jdouble angle2)
{
	cairo_arc_negative (cr, xc, yc, radius, angle1, angle2);
}

/* curve_to */
JNIEXPORT void JNICALL Java_gtkwire_widget_cairo_CairoGraphics_curve_1to
  (JNIEnv *env, jobject obj, jdouble x1, jdouble y1, jdouble x2, jdouble y2, jdouble x3, jdouble y3)
{
		cairo_curve_to (cr, x1, y1, x2, y2, x3, y3);
}

/* cairo_move_to */
JNIEXPORT void JNICALL Java_gtkwire_widget_cairo_CairoGraphics_move_1to
  (JNIEnv *env, jobject obj, jdouble x, jdouble y)
{
	cairo_move_to (cr, x, y);
}

/* line_to */
JNIEXPORT void JNICALL Java_gtkwire_widget_cairo_CairoGraphics_line_1to
  (JNIEnv *env, jobject obj, jdouble x, jdouble y)
{
	cairo_line_to (cr, x, y);
}

/* cairo_rectangle */
JNIEXPORT void JNICALL Java_gtkwire_widget_cairo_CairoGraphics_rectangle
  (JNIEnv *env, jobject obj, jdouble x, jdouble y, jdouble width, jdouble height)
{
	cairo_rectangle (cr, x, y, width, height);
}

/* text_path */
JNIEXPORT void JNICALL Java_gtkwire_widget_cairo_CairoGraphics_text_1path
  (JNIEnv *env, jobject obj, jstring jpstr)
{
	const char *path_str = (*env)->GetStringUTFChars (env, jpstr, NULL);
	cairo_text_path (cr, path_str);
	(*env)->ReleaseStringUTFChars(env, jpstr, path_str);
}

/* rel_curve_to */
JNIEXPORT void JNICALL Java_gtkwire_widget_cairo_CairoGraphics_rel_1curve_1to
  (JNIEnv *env, jobject obj, jdouble dx1, jdouble dy1, jdouble dx2, jdouble dy2, jdouble dx3, jdouble dy3)
{
	cairo_rel_curve_to (cr, dx1, dy1, dx2, dy2, dx3, dy3);
}

/* rel_line_to */
JNIEXPORT void JNICALL Java_gtkwire_widget_cairo_CairoGraphics_rel_1line_1to
  (JNIEnv *env, jobject obj, jdouble dx, jdouble dy)
{
	cairo_rel_line_to (cr, dx, dy);
}

/* rel_move_to */
JNIEXPORT void JNICALL Java_gtkwire_widget_cairo_CairoGraphics_rel_1move_1to
  (JNIEnv *env, jobject obj, jdouble dx, jdouble dy)
{
	cairo_rel_move_to (cr, dx, dy);
}

/* path_extents */
JNIEXPORT jobject JNICALL Java_gtkwire_widget_cairo_CairoGraphics_path_1extents
  (JNIEnv *env, jobject obj)
{
/*
	double *x1;
	double *y1;
	double *x2;
	double *y2;

	cairo_path_extents (cr, x1, y1, x2, y2);
	jobject r_obj = (*env)->NewObject (env, cairo_extents_cls, cairo_extents_constr_mid, *x1, *y1, *x2, *y2 );
	return r_obj;
*/
	return NULL;
}


//---------------------------------------------------------------- TRANSFORMATIONS

JNIEXPORT void JNICALL Java_gtkwire_widget_cairo_CairoGraphics_translate
  (JNIEnv *env, jobject obj, jdouble tx, jdouble ty)
{
	cairo_translate (cr, tx, ty);
}

JNIEXPORT void JNICALL Java_gtkwire_widget_cairo_CairoGraphics_scale
  (JNIEnv *env, jobject obj, jdouble sx, jdouble sy)
{
	cairo_scale (cr, sx, sy);
}

JNIEXPORT void JNICALL Java_gtkwire_widget_cairo_CairoGraphics_rotate
  (JNIEnv *env, jobject obj, jdouble angle)
{
	cairo_rotate (cr, angle);
}

JNIEXPORT void JNICALL Java_gtkwire_widget_cairo_CairoGraphics_transform
  (JNIEnv *env, jobject obj, jobject matrix)
{
/*
cairo_transform                     (cairo_t *cr,
                                                         const cairo_matrix_t *matrix);
*/
}


JNIEXPORT void JNICALL Java_gtkwire_widget_cairo_CairoGraphics_set_1matrix
  (JNIEnv *env, jobject obj, jobject matrix)
{
/*
cairo_set_matrix                    (cairo_t *cr,
                                                         const cairo_matrix_t *matrix);
*/
}

JNIEXPORT jobject JNICALL Java_gtkwire_widget_cairo_CairoGraphics_get_1matrix
  (JNIEnv *env, jobject obj)
{
/*
cairo_get_matrix                    (cairo_t *cr,
                                                         cairo_matrix_t *matrix);
*/
}

JNIEXPORT void JNICALL Java_gtkwire_widget_cairo_CairoGraphics_identity_1matrix
  (JNIEnv *env, jobject obj)
{
	cairo_identity_matrix (cr);
}

JNIEXPORT void JNICALL Java_gtkwire_widget_cairo_CairoGraphics_reset_1matrix
  (JNIEnv *env, jobject obj)
{

}
JNIEXPORT jobject JNICALL Java_gtkwire_widget_cairo_CairoGraphics_user_1to_1device
  (JNIEnv *env, jobject object, jdouble x, jdouble y)
{
	double *xp;
	double *yp;

	xp = &x;
	yp = &y;

	cairo_user_to_device (cr, xp, yp);
	jobject r_obj = (*env)->NewObject (env, cairo_point_cls, cairo_point_constr_mid, *xp, *yp);
	
	return r_obj;
}

JNIEXPORT jobject JNICALL Java_gtkwire_widget_cairo_CairoGraphics_user_1to_1device_1distance
  (JNIEnv *env, jobject object, jdouble x, jdouble y)
{
	double *xp;
	double *yp;

	xp = &x;
	yp = &y;

	cairo_user_to_device_distance  (cr, xp, yp);
	jobject r_obj = (*env)->NewObject (env, cairo_point_cls, cairo_point_constr_mid, *xp, *yp);
	
	return r_obj;
}

JNIEXPORT jobject JNICALL Java_gtkwire_widget_cairo_CairoGraphics_device_1to_1user
  (JNIEnv *env, jobject object, jdouble x, jdouble y)
{
	double *xp;
	double *yp;

	xp = &x;
	yp = &y;
	cairo_device_to_user (cr, xp, yp);
	jobject r_obj = (*env)->NewObject (env, cairo_point_cls, cairo_point_constr_mid, *xp, *yp);
	
	return r_obj;
}

JNIEXPORT jobject JNICALL Java_gtkwire_widget_cairo_CairoGraphics_device_1to_1user_1distance
  (JNIEnv *env, jobject object, jdouble x, jdouble y)
{
	double *xp;
	double *yp;

	xp = &x;
	yp = &y;

	cairo_device_to_user_distance (cr, xp, yp);
	jobject r_obj = (*env)->NewObject (env, cairo_point_cls, cairo_point_constr_mid, *xp, *yp);
	
	return r_obj;
}

//------------------------------------------------------------------------ PATTERN

static void 
add_pattern (int pid, cairo_pattern_t *pattern)
{
	PatternID *ldata;
	ldata = g_new (PatternID, 1);
	ldata->id = GINT_TO_POINTER(pid);
	ldata->pat = pattern;
	cairo_patterns_list = g_list_prepend (cairo_patterns_list, ldata);
}

/* destroys pattern and releases resources */
static void 
destroy_pattern (int pid)
{
	PatternID *list_data = NULL;
	GList *next = cairo_patterns_list;
	gboolean more = TRUE;
	while (more)
	{
		if (next == NULL)
		{
			more = FALSE;
		}
		else
		{
			list_data = next->data;
			/* Free resources */
			if( GPOINTER_TO_INT(list_data->id) == pid )
			{
				//g_free (list_data->id); poistettiib tuli core dump
				cairo_pattern_destroy (list_data->pat);
				g_free (list_data);
				cairo_patterns_list = g_list_delete_link (cairo_patterns_list, next);
				int l = g_list_length(cairo_patterns_list);
				more = FALSE;
			}
			else next = next->next;
		}
	}


}

static cairo_pattern_t*
get_pattern (int pid)
{
	PatternID *list_data = NULL;
	GList *next = cairo_patterns_list;
	while( next != NULL )
	{
		list_data = next->data;
		if( GPOINTER_TO_INT(list_data->id) == pid ) return list_data->pat;
		next = next->next;
	}
	return NULL;
}


JNIEXPORT void JNICALL Java_gtkwire_widget_cairo_CairoPattern_p_1create_1pattern_1radial
  (JNIEnv *env, jobject obj, jint pid, jdouble cx0, jdouble cy0, jdouble radius0, jdouble cx1, jdouble cy1, jdouble radius1)
{
	cairo_pattern_t *pat;
	pat = cairo_pattern_create_radial (cx0, cy0, radius0, cx1, cy1, radius1);
	add_pattern (pid, pat);
}

JNIEXPORT void JNICALL Java_gtkwire_widget_cairo_CairoPattern_p_1create_1pattern_1linear
  (JNIEnv *env, jobject obj, jint pid, jdouble x0, jdouble y0, jdouble x1, jdouble y1)
{
	cairo_pattern_t *pat;
	pat = cairo_pattern_create_linear (x0,  y0, x1, y1);
	add_pattern (pid, pat);
}

JNIEXPORT void JNICALL Java_gtkwire_widget_cairo_CairoPattern_p_1create_1pattern_1rgb
  (JNIEnv *env, jobject obj, jint pid, jdouble red, jdouble green, jdouble blue)
{
	cairo_pattern_t *pat;
	pat = cairo_pattern_create_rgb (red, green, blue);
	add_pattern (pid, pat);
}

JNIEXPORT void JNICALL Java_gtkwire_widget_cairo_CairoPattern_p_1create_1pattern_1create_1rgba
  (JNIEnv *env, jobject obj, jint pid, jdouble red, jdouble green, jdouble blue, jdouble alpha)
{
	cairo_pattern_t *pat;
	pat = cairo_pattern_create_rgba (red, green, blue, alpha);
	add_pattern (pid, pat);
}

JNIEXPORT void JNICALL Java_gtkwire_widget_cairo_CairoPattern_p_1destroy_1pattern
  (JNIEnv *env, jobject obj, jint pid )
{
	destroy_pattern (pid);
}


JNIEXPORT void JNICALL Java_gtkwire_widget_cairo_CairoPattern_p_1add_1color_1stop_1rgb
  (JNIEnv *env, jobject obj, jint pid, jdouble offset, jdouble red, jdouble green, jdouble blue)
{
	cairo_pattern_t *pat = get_pattern (pid);
	cairo_pattern_add_color_stop_rgb (pat, offset,red, green, blue);
}


JNIEXPORT void JNICALL Java_gtkwire_widget_cairo_CairoPattern_p_1add_1color_1stop_1rgba
  (JNIEnv *env, jobject obj, jint pid, jdouble offset, jdouble red, jdouble green, jdouble blue, jdouble alpha)
{
	cairo_pattern_t *pat = get_pattern (pid);
	cairo_pattern_add_color_stop_rgba (pat, offset,red, green, blue, alpha);
}

JNIEXPORT jint JNICALL Java_gtkwire_widget_cairo_CairoPattern_p_1cairo_1pattern_1status
  (JNIEnv *env, jobject obj, jint pid )
{

}

JNIEXPORT void JNICALL Java_gtkwire_widget_cairo_CairoPattern_p_1set_1extend
  (JNIEnv *env, jobject obj, jint pid, jint extend_type)
{

}


JNIEXPORT void JNICALL Java_gtkwire_widget_cairo_CairoPattern_p_1set_1filter
  (JNIEnv *env, jobject obj, jint pid, jint filter_type)
{

}

static jobject
get_cairo_graphics_rect_from_bounds (JNIEnv *env, double x, double y, double width, double height )
{
	return (*env)->NewObject (env, cairo_graphics_rect_cls, cairo_graphics_rect_mid, x, y, width, height);
}

/*
* --------------------------------------------------------- TEST IMAGE
*/
JNIEXPORT void JNICALL 
Java_gtkwire_widget_cairo_CairoGraphics_testDraw (JNIEnv *env, jobject obj)
{
	double xc = 128.0;
	double yc = 128.0;
	double radius = 100.0;
	double angle1 = 45.0  * (G_PI/180.0);  /* angles are specified */
	double angle2 = 180.0 * (G_PI/180.0);  /* in radians           */
	
	cairo_set_line_width (cr, 10.0);
	cairo_arc (cr, xc, yc, radius, angle1, angle2);
	cairo_stroke (cr);
	
	/* draw helping lines */
	cairo_set_source_rgba (cr, 1, 0.2, 0.2, 0.6);
	cairo_set_line_width (cr, 6.0);
	
	cairo_arc (cr, xc, yc, 10.0, 0, 2*G_PI);
	cairo_fill (cr);
	
	cairo_arc (cr, xc, yc, radius, angle1, angle1);
	cairo_line_to (cr, xc, yc);
	cairo_arc (cr, xc, yc, radius, angle2, angle2);
	cairo_line_to (cr, xc, yc);
	cairo_stroke (cr);
}

